package com.plus.config.sign;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.plus.entity.customEntity.ResponseSign;
import com.plus.exception.SignServiceException;
import com.plus.utils.SiginUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.SortedMap;
import java.util.TreeMap;

/**
 * @program: spring-boot-encrypt
 * @ClassName SignatureValidation
 * @description:
 * @author: AI
 * @create: 2023-12-01 14:36
 * @Version 1.0
 **/
@Aspect
@Component
public class SignatureValidation {

    /**
     * 签名秘钥
     */
    @Value("${spring.security.sign.secret}")
    private String SECRET;

    /**
     * 版本号
     */
    @Value("${spring.security.sign.version}")
    private String VERSION;

    /**
     * 验签切点(完整的找到设置的文件地址)
     */
    @Pointcut("execution(@com.plus.config.sign.SignValidation * *(..))")
    private void verifyUserKey() {
    }

    /**
     * 获取请求数据，并校验签名数据
     */
    @Before("verifyUserKey()")
    public void doBasicProfiling(JoinPoint point) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        //HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();
        String sign = "" ;
        String timestamp = "" ;
        String version = "";
        SortedMap<String,Object> sortedMap = new TreeMap<String,Object>();
        for ( Object obj  :point.getArgs()) {
            JSONObject jsonObject = JSONUtil.parseObj(obj);

            if(!StrUtil.isEmptyIfStr(jsonObject.get("timestamp"))){
                timestamp = jsonObject.get("timestamp").toString();

                //这里可以进一步判断时间戳，比如时间戳间隔在5分钟之内有效
                long nowTimeSamp = System.currentTimeMillis();
                double s = (nowTimeSamp - Long.parseLong(timestamp)) / 60;//分钟
//                if(s > 5){
//                    throw new SignServiceException("500","签名已过期");
//                }
                sortedMap.put("timestamp", timestamp);
            }

            if( !StrUtil.isEmptyIfStr(jsonObject.get("sign"))){
                sign = jsonObject.get("sign").toString();
            }
            if(!StrUtil.isEmptyIfStr(jsonObject.get("version"))){
                version = jsonObject.get("version").toString();
                sortedMap.put("version", version);
            }

            if(!StrUtil.isEmptyIfStr(jsonObject.get("data"))){
                String dataStr = jsonObject.get("data").toString();
                if(JSONUtil.isJsonArray(dataStr)){
                    sortedMap.put("data", JSONUtil.parseArray(dataStr).toString());
                }
                sortedMap.put("data", dataStr);
            }
        }

        if (StrUtil.isEmptyIfStr(sign)) {
            System.out.println("签名为空。");
            throw new SignServiceException("500","签名为空");
        }

        //新的签名
        String newSign = SiginUtil.createSign(sortedMap,SECRET);
        if (!newSign.equals(sign.toUpperCase())) {
            System.out.println("签名认证失败");
            throw new SignServiceException("500","签名认证失败");
        }

    }

    /**
     *
     * @param point
     * @param responseObject 返回参数
     */
    @AfterReturning(pointcut="verifyUserKey()",returning="responseObject")
    public void afterReturning(JoinPoint point,Object responseObject) {
        //HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        ResponseSign responseSign = (ResponseSign) responseObject;
        responseSign.setTimestamp(String.valueOf(System.currentTimeMillis()));
        responseSign.setVersion(VERSION);
        //生成签名
        SortedMap<String,Object> sortedMap = new TreeMap<String,Object>();
        sortedMap.put("timestamp", responseSign.getTimestamp());

        //获取动态秘钥
        String c_secret = SECRET;
        if(!StringUtils.isEmpty(responseSign.getSecret())){
            c_secret = responseSign.getSecret();
        }
        String objStr = JSON.toJSONString(responseSign.getData());
        sortedMap.put("data",objStr);
        sortedMap.put("version", responseSign.getVersion());
        String sign = SiginUtil.createSign(sortedMap,c_secret);
        responseSign.setSign(sign);
    }

}
